feat(davinci-client): add form image collector#698
Conversation
🦋 Changeset detectedLatest commit: 1873072 The changes in this PR will be included in the next version bump. This PR includes changesets to release 12 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Warning Review limit reached
More reviews will be available in 47 minutes and 59 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses rolling per-developer review limits. Reviews become available again as older review attempts age out of the rolling limit window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (10)
📝 WalkthroughWalkthroughAdds ChangesImageCollector Feature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
View your CI Pipeline Execution ↗ for commit 6d4382b
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗ ☁️ Nx Cloud last updated this comment at |
@forgerock/davinci-client
@forgerock/device-client
@forgerock/journey-client
@forgerock/oidc-client
@forgerock/protect
@forgerock/sdk-types
@forgerock/sdk-utilities
@forgerock/iframe-manager
@forgerock/sdk-logger
@forgerock/sdk-oidc
@forgerock/sdk-request-middleware
@forgerock/storage
commit: |
|
Deployed 22fec8c to https://ForgeRock.github.io/ping-javascript-sdk/pr-698/22fec8cd19283d5a19296893e7d9b331b3dc9340 branch gh-pages in ForgeRock/ping-javascript-sdk |
📦 Bundle Size Analysis📦 Bundle Size Analysis🚨 Significant Changes🔻 @forgerock/device-client - 0.0 KB (-10.0 KB, -100.0%) 📊 Minor Changes📈 @forgerock/davinci-client - 54.4 KB (+0.6 KB) ➖ No Changes➖ @forgerock/oidc-client - 35.2 KB 14 packages analyzed • Baseline from latest Legend🆕 New package ℹ️ How bundle sizes are calculated
🔄 Updated automatically on each push to this PR |
Codecov Report✅ All modified and coverable lines are covered by tests. ❌ Your project status has failed because the head coverage (22.02%) is below the target coverage (40.00%). You can increase the head coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #698 +/- ##
==========================================
+ Coverage 18.07% 22.02% +3.95%
==========================================
Files 155 157 +2
Lines 24398 25205 +807
Branches 1203 1479 +276
==========================================
+ Hits 4410 5552 +1142
+ Misses 19988 19653 -335
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
packages/davinci-client/src/lib/collector.types.test-d.ts (1)
658-672: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winAdd a companion type test without
hyperlinkUrlto lock optional semantics.Current coverage validates the “present” case only. Adding a second
ImageCollectorsample withouthyperlinkUrlwould protect against accidentally making it required later.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/davinci-client/src/lib/collector.types.test-d.ts` around lines 658 - 672, Add a second type test case for ImageCollector that omits the hyperlinkUrl property from the output object. Create a new test (likely another it block) that validates the InferNoValueCollectorType type inference for ImageCollector but with a minimal output structure that excludes hyperlinkUrl, ensuring the type definition correctly treats hyperlinkUrl as optional and prevents accidental breaking changes that might make it required.packages/davinci-client/src/lib/collector.types.ts (1)
640-649: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winAlign
ImageCollectordocs with the declared requireddescriptionfield.The JSDoc says
descriptionis optional, butoutput.descriptionis typed as required (string). Please make the comment consistent with the type contract.Suggested doc-only fix
- * hyperlink URL (`hyperlink.url`), and an optional `description` (alt text). + * hyperlink URL (`hyperlink.url`), and `description` (alt text).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/davinci-client/src/lib/collector.types.ts` around lines 640 - 649, The JSDoc comment for the `ImageCollector` interface incorrectly describes `description` as an optional field when the type definition shows `description: string` as required (non-nullable). Update the comment above the `ImageCollector` interface to remove the "optional" designation for `description` and accurately reflect that it is a required field in the output type, while keeping the reference to it being alt text.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@e2e/davinci-suites/src/form-image.test.ts`:
- Around line 22-25: The test assertion for the formImage src attribute uses a
brittle full URL equality check that will fail if query parameters, their order,
or optimization values change. Instead of checking the entire URL with
toHaveAttribute, use a more flexible assertion that checks if the src contains
or matches just the essential parts of the URL (such as the base image path from
destinationcanada.com without the query parameters) to make the test more
resilient to parameter changes.
---
Nitpick comments:
In `@packages/davinci-client/src/lib/collector.types.test-d.ts`:
- Around line 658-672: Add a second type test case for ImageCollector that omits
the hyperlinkUrl property from the output object. Create a new test (likely
another it block) that validates the InferNoValueCollectorType type inference
for ImageCollector but with a minimal output structure that excludes
hyperlinkUrl, ensuring the type definition correctly treats hyperlinkUrl as
optional and prevents accidental breaking changes that might make it required.
In `@packages/davinci-client/src/lib/collector.types.ts`:
- Around line 640-649: The JSDoc comment for the `ImageCollector` interface
incorrectly describes `description` as an optional field when the type
definition shows `description: string` as required (non-nullable). Update the
comment above the `ImageCollector` interface to remove the "optional"
designation for `description` and accurately reflect that it is a required field
in the output type, while keeping the reference to it being alt text.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d0ed34c7-4971-4ef6-b40c-f2162503f81c
📒 Files selected for processing (17)
.changeset/curly-wolves-swim.mde2e/davinci-app/components/form-image.tse2e/davinci-app/main.tse2e/davinci-app/server-configs.tse2e/davinci-suites/src/form-fields.test.tse2e/davinci-suites/src/form-image.test.tspackages/davinci-client/api-report/davinci-client.api.mdpackages/davinci-client/api-report/davinci-client.types.api.mdpackages/davinci-client/src/lib/collector.types.test-d.tspackages/davinci-client/src/lib/collector.types.tspackages/davinci-client/src/lib/collector.utils.test.tspackages/davinci-client/src/lib/collector.utils.tspackages/davinci-client/src/lib/davinci.types.tspackages/davinci-client/src/lib/node.reducer.test.tspackages/davinci-client/src/lib/node.reducer.tspackages/davinci-client/src/lib/node.types.test-d.tspackages/davinci-client/src/lib/node.types.ts
cerebrl
left a comment
There was a problem hiding this comment.
I'd like to simplify the property names, but otherwise, looks good.
| imageUrl: string; | ||
| description: string; | ||
| hyperlinkUrl?: string; |
There was a problem hiding this comment.
I'd like to avoid compound property names, if possible. How do you feel about borrowing from HTML here and just use src, instead of imageUrl and href, instead of hyperlinkUrl?
There was a problem hiding this comment.
I wanted to keep the parity with what we receive from Davinci, but totally open to using simpler names. This is what we receive from Davinci
"type": "IMAGE",
"key": "<field key>",
"description": "<alt text>",
"imageUrl": "<absolute URL>",
"hyperlinkUrl": "<absolute URL>"
Do you have a preference there? I feel it's easier to reason through and debug when we keep the same properties as what Davinci returns. Besides, I checked and almost all collectors except for QrCodeField follow property names the same as what Davinci returns.
I can change it to alt, src, href. However, would be good to know your opinion on whether we should keep that parity or borrow from HTML.
There was a problem hiding this comment.
I thought about this further. davinci.types.ts already maps what Davinci returns, so we can rename those properties independently from Davinci in collector.types.ts file. Updated the description, imageUrl, hyperlinkUrl properties to alt, src, href respectively.
ancheetah
left a comment
There was a problem hiding this comment.
Lgtm, some minor comments and suggestions
| output: { | ||
| key: `${field.key || field.type}-${idx}`, | ||
| label: field.content, | ||
| label: 'content' in field ? field.content : '', |
There was a problem hiding this comment.
What do you think about copying field.description here into label so it's not empty?
There was a problem hiding this comment.
I see what you mean, something like field.content ?? field.description ?? ''
Among the NoValueCollectors, description is used only by ImageCollector. We can put that as a label, but it seems like we're adding an image collector specific property to a generic NoValueCollector.
However, if we were to extend no value collector for other fields later and if we find that description is an alternative property to content, maybe we can add it there then.
Right now, I feel like it might cause future bugs where NoValueCollector now checks for description if content is null, which is something specific to only image collector, and description may not be a property or description might mean something else for other no value collectors that we add later.
There was a problem hiding this comment.
What if we only override the label property in the returnImageCollector function?
There was a problem hiding this comment.
Yeah, that sounds interesting. I'm thinking this will change the naming for alt to label. I do like the idea that we can reuse an existing field but at the same time if we prefer HTML specific names like src, alt, href, like Justin mentioned in the earlier comment, then it kind of deviates in terms of naming.
There was a problem hiding this comment.
It doesn't have to change the alt naming necessarily. The value of field.description could be placed into both alt and label. We do something similar in NoValueCollectors where we sometimes put field.content into both output.label and output.content. I think having some value for label instead of leaving it blank keeps it consistent with other collectors from this category and avoids having a "dead" property.
There was a problem hiding this comment.
Ah, okay. I can do that and continue to use alt. That is perfect, if that is what you are referring to. Just pushed the commit!
|
@vatsalparikh One more question, should this have a |
Is there a reason to hold back ImageCollector feature in 2.1 release? |
I'm not sure. It's a question for product wether or not it should go out. I would think if we are starting QA, we should be in code freeze. |
0f1d875 to
6d4382b
Compare
There was a problem hiding this comment.
Important
At least one additional CI pipeline execution has run since the conclusion below was written and it may no longer be applicable.
Nx Cloud is proposing a fix for your failed CI:
We reverted the waitForRequest URL filter in form-fields.test.ts from showForm back to customForm, as the DaVinci API's form submission POST request URL contains customForm, not showForm. The showForm filter caused the waitForRequest promise to never resolve, resulting in a 30-second timeout. This fix restores the correct URL matching so the test can proceed after the Submit button is clicked.
Tip
✅ We verified this fix by re-running @forgerock/davinci-suites:e2e-ci--src/form-fields.test.ts.
diff --git a/e2e/davinci-suites/src/form-fields.test.ts b/e2e/davinci-suites/src/form-fields.test.ts
index 101a3e9..c58d792 100644
--- a/e2e/davinci-suites/src/form-fields.test.ts
+++ b/e2e/davinci-suites/src/form-fields.test.ts
@@ -71,7 +71,7 @@ test('Should render form fields', async ({ page }) => {
await expect(page.getByRole('button', { name: 'Flow Link' })).toBeVisible();
const requestPromise = page.waitForRequest(
- (request) => request.url().includes('showForm') && request.method() === 'POST',
+ (request) => request.url().includes('customForm') && request.method() === 'POST',
);
await page.getByRole('button', { name: 'Submit' }).click();
Or Apply changes locally with:
npx nx-cloud apply-locally rp64-yw5H
Apply fix locally with your editor ↗ View interactive diff ↗
🎓 Learn more about Self-Healing CI on nx.dev
e0cdac0 to
3de5f3a
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/davinci-client/src/lib/collector.utils.ts`:
- Line 1009: The `alt` property assignment on line 1009 uses `field.description`
directly without a fallback value, while the `label` property on line 1007 uses
`field.description ?? ''` to provide an empty string default. This inconsistency
means `alt` will be `undefined` when `field.description` is missing, while
`label` will be an empty string. Apply the same defensive null coalescing
pattern to the `alt` assignment to use an empty string fallback when
`field.description` is absent, ensuring consistent behavior between both
properties.
- Line 1008: The `src` property assignment using `field.imageUrl` lacks a
fallback mechanism for when imageUrl is null or undefined, resulting in invalid
src attributes. Add a fallback value to the `src: field.imageUrl` assignment by
using the pattern `src: field.imageUrl || ''` to match the approach used in the
`returnQrCodeCollector` function, ensuring the image element always has a valid
(even if empty) src attribute.
- Line 1004: The returnImageCollector function explicitly sets error: null,
which overrides validation errors from the base returnNoValueCollector, creating
inconsistency with other collectors like returnQrCodeCollector and
returnReadOnlyCollector that inherit the base error state. Either remove the
explicit error: null assignment from returnImageCollector to inherit the base
validation behavior like the other collectors do, or keep it and add a clear
comment documenting why IMAGE collectors specifically need to bypass validation
error checking while other collectors do not.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: b30cfd02-44b0-47b4-bd27-24e01a2e20d8
📒 Files selected for processing (10)
.changeset/curly-wolves-swim.mde2e/davinci-app/components/form-image.tse2e/davinci-suites/src/form-image.test.tspackages/davinci-client/api-report/davinci-client.api.mdpackages/davinci-client/api-report/davinci-client.types.api.mdpackages/davinci-client/src/lib/collector.types.test-d.tspackages/davinci-client/src/lib/collector.types.tspackages/davinci-client/src/lib/collector.utils.test.tspackages/davinci-client/src/lib/collector.utils.tspackages/davinci-client/src/lib/node.reducer.test.ts
✅ Files skipped from review due to trivial changes (1)
- .changeset/curly-wolves-swim.md
🚧 Files skipped from review as they are similar to previous changes (8)
- packages/davinci-client/src/lib/collector.types.test-d.ts
- e2e/davinci-suites/src/form-image.test.ts
- packages/davinci-client/src/lib/node.reducer.test.ts
- e2e/davinci-app/components/form-image.ts
- packages/davinci-client/src/lib/collector.types.ts
- packages/davinci-client/src/lib/collector.utils.test.ts
- packages/davinci-client/api-report/davinci-client.api.md
- packages/davinci-client/api-report/davinci-client.types.api.md
|
|
||
| return { | ||
| ...base, | ||
| error: null, |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Compare error handling across collector factory functions
# Check if other collectors override the error property
rg -A 10 'export function return.*Collector' packages/davinci-client/src/lib/collector.utils.ts | rg -C 2 'error:'Repository: ForgeRock/ping-javascript-sdk
Length of output: 432
🏁 Script executed:
#!/bin/bash
# Read the area around line 1004 to identify which collector this is
sed -n '990,1020p' packages/davinci-client/src/lib/collector.utils.tsRepository: ForgeRock/ping-javascript-sdk
Length of output: 1413
🏁 Script executed:
#!/bin/bash
# Search for returnQrCodeCollector and returnReadOnlyCollector functions and their error handling
rg -B 5 -A 15 'export function returnQrCodeCollector|export function returnReadOnlyCollector' packages/davinci-client/src/lib/collector.utils.tsRepository: ForgeRock/ping-javascript-sdk
Length of output: 1675
🏁 Script executed:
#!/bin/bash
# Get a complete view of all collector factory functions and their error property handling
ast-grep outline packages/davinci-client/src/lib/collector.utils.ts | head -50Repository: ForgeRock/ping-javascript-sdk
Length of output: 2341
🏁 Script executed:
#!/bin/bash
# Find and read the returnNoValueCollector implementation
sed -n '905,939p' packages/davinci-client/src/lib/collector.utils.tsRepository: ForgeRock/ping-javascript-sdk
Length of output: 1435
Remove explicit error: null override or document why IMAGE collectors bypass validation errors.
returnImageCollector explicitly sets error: null, overriding validation from the base returnNoValueCollector. In contrast, returnQrCodeCollector and returnReadOnlyCollector inherit the base error state, which validates that content and type fields exist.
Either IMAGE collectors should inherit the base validation (removing the explicit null), or this difference should be documented with a comment explaining why IMAGE collectors skip error validation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/davinci-client/src/lib/collector.utils.ts` at line 1004, The
returnImageCollector function explicitly sets error: null, which overrides
validation errors from the base returnNoValueCollector, creating inconsistency
with other collectors like returnQrCodeCollector and returnReadOnlyCollector
that inherit the base error state. Either remove the explicit error: null
assignment from returnImageCollector to inherit the base validation behavior
like the other collectors do, or keep it and add a clear comment documenting why
IMAGE collectors specifically need to bypass validation error checking while
other collectors do not.
| output: { | ||
| ...base.output, | ||
| label: field.description ?? '', | ||
| src: field.imageUrl, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Consider adding fallback for src to handle missing imageUrl.
The src property is set directly from field.imageUrl without a fallback. If imageUrl is null or undefined, the resulting image element will have an invalid src attribute. For comparison, returnQrCodeCollector (line 983) uses field.content || '' to provide a fallback for its src property.
🛡️ Proposed fix to add fallback for src
label: field.description ?? '',
- src: field.imageUrl,
+ src: field.imageUrl ?? '',
alt: field.description,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| src: field.imageUrl, | |
| label: field.description ?? '', | |
| src: field.imageUrl ?? '', | |
| alt: field.description, |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/davinci-client/src/lib/collector.utils.ts` at line 1008, The `src`
property assignment using `field.imageUrl` lacks a fallback mechanism for when
imageUrl is null or undefined, resulting in invalid src attributes. Add a
fallback value to the `src: field.imageUrl` assignment by using the pattern
`src: field.imageUrl || ''` to match the approach used in the
`returnQrCodeCollector` function, ensuring the image element always has a valid
(even if empty) src attribute.
| ...base.output, | ||
| label: field.description ?? '', | ||
| src: field.imageUrl, | ||
| alt: field.description, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Add fallback for alt to match label handling.
The alt property uses field.description directly without a fallback, while label on line 1007 uses field.description ?? ''. This inconsistency means that when field.description is absent, label will be an empty string but alt will be undefined. Based on the unit tests (which verify label defaults to '' when description is missing), the same defensive handling should apply to alt.
🛡️ Proposed fix to add fallback for alt
label: field.description ?? '',
src: field.imageUrl,
- alt: field.description,
+ alt: field.description ?? '',
...(field.hyperlinkUrl ? { href: field.hyperlinkUrl } : {}),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| alt: field.description, | |
| label: field.description ?? '', | |
| src: field.imageUrl, | |
| alt: field.description ?? '', | |
| ...(field.hyperlinkUrl ? { href: field.hyperlinkUrl } : {}), |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/davinci-client/src/lib/collector.utils.ts` at line 1009, The `alt`
property assignment on line 1009 uses `field.description` directly without a
fallback value, while the `label` property on line 1007 uses `field.description
?? ''` to provide an empty string default. This inconsistency means `alt` will
be `undefined` when `field.description` is missing, while `label` will be an
empty string. Apply the same defensive null coalescing pattern to the `alt`
assignment to use an empty string fallback when `field.description` is absent,
ensuring consistent behavior between both properties.
JIRA Ticket
https://pingidentity.atlassian.net/browse/SDKS-5101
Review Note:
The third commit davinci-client: add image collector e2e test against old env is only added temporarily. Right now, only the old Davinci env has the feature flag DV-21617-forms-image-component-sdk-response enabled. So instead of updating the form to match the old env, I've added a new file form-image.test.ts and added old Davinci config to server-configs.ts file as a separate commit. Will remove this commit as soon as the flag is enabled for new Davinci console.
Description
Adds support for the IMAGE field type in DaVinci forms. When a form includes an image component, the SDK now parses it into an ImageCollector, a read-only collector with description, imageUrl, and hyperlink properties.
How to test
Recording
Screen.Recording.2026-06-22.at.11.52.23.AM.mov
Summary by CodeRabbit
New Features
Tests